﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Threading;
using System.Security.Cryptography.X509Certificates;

namespace NHINDirect
{
    public class SystemX509Store : CertificateStore
    {
        X509Store m_store;
        
        public SystemX509Store(X509Store store, Predicate<X509Certificate2> criteria)
            : base(criteria)
        {
            if (store == null)
            {
                throw new ArgumentNullException();
            }
            
            this.m_store = store;
        }
                
        public override X509Certificate2Collection this[string subjectName]
        {
            get
            {
                return this.m_store.Certificates.Find(X509FindType.FindBySubjectName, subjectName, false);
            }
        }
                
        public override bool Contains(X509Certificate2 cert)
        {
            return this.m_store.Certificates.Contains(cert);
        }
        
        public override void Add(X509Certificate2 cert)
        {
            if (cert == null)
            {
                throw new ArgumentNullException();
            }

            lock (this.m_store)
            {
                this.ValidateCriteria(cert);
                this.m_store.Add(cert);
            }
        }

        public override void Remove(X509Certificate2 cert)
        {
            lock(this.m_store)
            {
                this.m_store.Remove(cert);
            }
        }
                        
        public override IEnumerable<X509Certificate2> GetCertificates()
        {
            X509Certificate2Collection certs;
            lock(this.m_store)
            {
                certs = this.m_store.Certificates;
            }
            
            return certs.Enumerate(this.Criteria);
        }
                
        public override void Dispose()
        {
            if (this.m_store != null)
            {
                this.m_store.Close();
                this.m_store = null;
            }
        }
        
        public const string AnchorCertsStoreName = "NHINDAnchors";
        public const string PrivateCertsStoreName = "NHINDPrivate";
        public const string ExternalCertsStoreName = "NHINDExternal";
        
        public static SystemX509Store OpenAnchor()
        {
            return new SystemX509Store(CryptoExtensions.OpenStoreReadWrite(AnchorCertsStoreName, StoreLocation.LocalMachine), null);
        }
        public static SystemX509Store OpenPrivate()
        {
            return new SystemX509Store(CryptoExtensions.OpenStoreReadWrite(PrivateCertsStoreName, StoreLocation.LocalMachine),
                                        x => x.HasPrivateKey);
        }
        public static SystemX509Store OpenExternal()
        {
            return new SystemX509Store(CryptoExtensions.OpenStoreReadWrite(ExternalCertsStoreName, StoreLocation.LocalMachine), null);
        }
    }
}
